home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / submit / ch_bind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  19.0 KB  |  804 lines

  1. /* ch_bind.c - binds reformatting channels to a recipient address */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/ch_bind.c,v 6.0 1991/12/18 20:28:02 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/submit/RCS/ch_bind.c,v 6.0 1991/12/18 20:28:02 jpo Rel $
  9.  *
  10.  * $Log: ch_bind.c,v $
  11.  * Revision 6.0  1991/12/18  20:28:02  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "head.h"
  19. #include "q.h"
  20. #include "ch_bind.h"
  21.  
  22.  
  23. extern void        err_abrt();
  24. extern LIST_BPT        *bodies_all, *headers_all;
  25.  
  26.  
  27. /* -- static variables -- */
  28. static FILTER        *filterlist = NULL;
  29. static TYPES        *typelist;
  30. static MAT        *mainmatrix;
  31. static int        matsize;
  32. static FLAT        *flattenlist = NULL, *unflatlist = NULL;
  33.  
  34.  
  35. /* -- local routines -- */
  36. int            ch_bind();
  37. void            fmt_init();
  38.  
  39. static FILTER        *getfilter();
  40. static FILTER        *name2filter();
  41. static FLAT        *add2flatlist();
  42. static FLAT        *flttype2ptr();
  43. static LIST        *additem();
  44. static LIST        *copylist();
  45. static LIST        *getitem();
  46. static LIST        *inslist();
  47. static MAT        *initmat();
  48. static TYPES        *addchantypes();
  49. static TYPES        *name2type();
  50. static int        isinlist();
  51. static void        addmat();
  52. static void        do_calc();
  53. static void        flatten();
  54. static void        format();
  55. static void        freelist();
  56. static void        get_formatters();
  57. static void        initform();
  58. static void        unflat();
  59.  
  60.  
  61.  
  62.  
  63. /* ---------------------  Begin  Routines --------------------------------- */
  64.  
  65.  
  66. /* --- *** Start Description *** ---
  67.    
  68.    ch_bind (ad, p, pfmts, pcost, punknown)
  69.    ADDR            *ad;
  70.    LIST_RCHAN    *p;
  71.    LIST_RCHAN    **pfmts;
  72.    int        *pcost, *punknown;
  73.    
  74.    Parameters required:
  75.    - The channel calling submit
  76.    - The flatness of the channel
  77.    - The channel/mta pair used to get to the Next Hop hostname ( p )
  78.    - The list of Encoded Information Types within the message
  79.    (Qstruct.encodedinfo.eit_types)
  80.    - A pointer to a list of Reformatting channels (ad->ad_fmtchan)
  81.  
  82.    Example:
  83.    ch_inbound           =  x400in
  84.    content_in        =  "rfc" or "p2"
  85.    p             =  li_mta = ukc.ac.uk     li_chan => JANET
  86.    ( or li_mta = stl.stc.co.uk li_chan => PSS )
  87.    Qstruct.encodedinfo
  88.    .eit_types    =  ia5Text, voice
  89.    ad->ad_fmtchan       =  unflattenp2, voice2text, flattenrfc
  90.    
  91.    Routine:
  92.    - Calculates the reformatting channels.
  93.    - Updates ad_fmtchan.
  94.    - Returns OK or NOTOK.
  95.    
  96.    
  97.    fmt_init ()
  98.    - Initialise reformatting stuff
  99.    
  100.    --- *** End Description *** --- */
  101.  
  102.  
  103.  
  104.  
  105. /* ------------------------------------------------------------------------ */
  106.  
  107.  
  108.  
  109.  
  110.  
  111. void fmt_init ()
  112. {
  113.     PP_TRACE (("ch_bind/fmt_init ()"));
  114.     
  115.     initform ();
  116.     get_formatters ();
  117.     do_calc (mainmatrix);
  118. }
  119.  
  120. static FLAT *add2flatlist (list, name, type)
  121. FLAT    *list;
  122. char    *name, *type;
  123. {
  124.     FLAT    *ptr;
  125.     
  126.     ptr = (FLAT *) smalloc (sizeof (FLAT));
  127.     ptr->flt_type = strdup (type);
  128.     ptr->flt_name = strdup ( name);
  129.     ptr->flt_next = list;
  130.     return (ptr);
  131. }
  132.  
  133. static void unflat (name, type)    /* Add an unflattening channel to the list */
  134. char    *name, *type;           /* of unflattening channels */
  135. {
  136.     PP_TRACE (("ch_bind/unflat (%s, %s)", name, type));
  137.     
  138.     if (flttype2ptr (unflatlist, type) != NULL)
  139.     {
  140.         PP_LOG (LLOG_EXCEPTIONS,
  141.             ("ch_bind/UNFLAT type %s is in use already", type));
  142.         return;
  143.     }
  144.     unflatlist = add2flatlist (unflatlist, name, type);
  145. }
  146.  
  147. static void flatten (name, type) /* Add a Flattening channel to the list */
  148. char    *name, *type;           /* of flattening channels */
  149. {
  150.     PP_TRACE (("ch_bind/flatten (%s, %s)", name, type));
  151.     
  152.     if (flttype2ptr (flattenlist, type) != NULL)
  153.     {
  154.         PP_LOG (LLOG_EXCEPTIONS,
  155.             ("ch_bind/FLATTEN type %s is in use already\n",
  156.              type));
  157.         return;
  158.     }
  159.     flattenlist = add2flatlist (flattenlist, name, type);
  160. }
  161.  
  162. static FLAT *flttype2ptr (list, type)
  163. char    *type;
  164. FLAT    *list;
  165. {
  166.     PP_DBG (("ch_bind/flttype2ptr (list, %s)", type));
  167.     
  168.     if (type == NULLCP)
  169.         return NULL;
  170.     for (; list != NULL; list = list->flt_next)
  171.         if (strcmp (list->flt_type, type) == 0)
  172.             return (list);
  173.     PP_TRACE (("ch_bind/flttype2ptr - NO match"));
  174.     return (NULL);
  175. }
  176.  
  177. static FILTER *name2filter (name) /* Format Channel name to pointer to struct */
  178. char    *name;
  179. {
  180.     FILTER  *ptr;
  181.     
  182.     PP_TRACE (("ch_bind/name2filter (%s)", name));
  183.     
  184.     for (ptr = filterlist; ptr != NULL; ptr = ptr->fil_next)
  185.         if (strcmp (name, ptr->fil_name) == 0)
  186.             return (ptr);
  187.     return (NULL);
  188. }
  189.  
  190.  
  191. static LIST *inslist (list, new)
  192. LIST    *list, *new;
  193. {
  194.     
  195.     if (new == NULL)
  196.     {
  197.         PP_TRACE (("ch_bind/inslist (NULL)"));
  198.         return (list);
  199.     }
  200.     
  201.     PP_TRACE (("ch_bind/inslist (%s)", new -> li_name ));
  202.     list = inslist (list, new->li_next);
  203.     /* SEK - should replace with for loop */
  204.     if (!isinlist (list, new))
  205.     {
  206.         new->li_next = list;
  207.         list = new;
  208.     }
  209.     return (list);
  210. }
  211.  
  212. static int isinlist (list, item)
  213. LIST    *list, *item;
  214. {
  215.     
  216.     for (; list != NULL; list = list->li_next)
  217.         if (strcmp (list->li_name, item->li_name) == 0)
  218.             return (1);
  219.     return (0);
  220. }
  221.  
  222. static TYPES *addchantypes (atypelist, punknown)
  223. LIST_BPT        *atypelist;
  224. int        *punknown;
  225. {
  226.     register TYPES  *list, *all, *storenum;
  227.     
  228.     PP_TRACE (("ch_bind/addchantypes (atypelist)"));
  229.     *punknown = FALSE;
  230.     list = NULL;
  231.     for (; atypelist != NULL; atypelist = atypelist->li_next)
  232.     {
  233.         if ((storenum = name2type (atypelist->li_name)) == NULL)
  234.         {
  235.             PP_LOG (LLOG_EXCEPTIONS,
  236.                 ("ch_bind/%s is not a defined type",
  237.                  atypelist->li_name));
  238.             *punknown = TRUE;
  239.             continue;
  240.         }
  241.         all = (TYPES *) smalloc (sizeof (TYPES));
  242.         all->ty_next = list;
  243.         list = all;
  244.         all->ty_name = atypelist->li_name;
  245.         all->ty_number = storenum->ty_number;
  246.     }
  247.     return (list);
  248. }
  249.  
  250.  
  251. static TYPES *name2type (str)
  252. char    *str;
  253. {
  254.     TYPES   *ptr;
  255.     
  256.     PP_TRACE (("ch_bind/name2type (%s)", str));
  257.     for (ptr = typelist; ptr != NULL; ptr = ptr->ty_next)
  258.         if (strcmp (str, ptr->ty_name) == 0)
  259.             return (ptr);
  260.     return (NULL);
  261. }
  262.  
  263. static void format (fname, fcost, ffrom, fto)
  264. int     fcost;
  265. char    *fname, *ffrom, *fto;   /* Don't use FNAME, pass the CHAN pointer */
  266. {
  267.     int     x, y;
  268.     FILTER  *ptr;
  269.     TYPES   *type;
  270.     
  271.     PP_TRACE (("ch_bind/format (%s, %d, %s, %s)",
  272.            fname, fcost, ffrom, fto));
  273.     
  274.     if ((type = name2type (ffrom)) == NULL)
  275.     {
  276.         PP_LOG (LLOG_EXCEPTIONS,
  277.             ("ch_bind/%s is not a defined type", ffrom));
  278.         return;
  279.     }
  280.     x = type->ty_number;
  281.     if ((type = name2type (fto)) == NULL)
  282.     {
  283.         PP_LOG (LLOG_EXCEPTIONS,
  284.             ("ch_bind/%s is not a defined type", fto));
  285.         return;
  286.     }
  287.     y = type->ty_number;
  288.     addmat (mainmatrix, x, y, fcost, fname);
  289.     ptr = getfilter ();
  290.     ptr->fil_next = filterlist;
  291.     filterlist = ptr;
  292.     ptr->fil_name = fname;
  293.     ptr->fil_from = ffrom;
  294.     ptr->fil_to = fto;
  295. }
  296.  
  297. static LIST *copylist (list)
  298. register LIST   *list;
  299. {
  300.     register LIST   *tmpitem, *ptr;
  301.     
  302.     PP_DBG (("ch_bind/copylist (list)"));
  303.     
  304.     for (tmpitem = NULL; list != NULL; list = list->li_next)
  305.     {
  306.         ptr = getitem ();
  307.         ptr->li_name = list->li_name;
  308.         tmpitem = additem (tmpitem, ptr);
  309.     }
  310.     return (tmpitem);
  311. }
  312.  
  313.  
  314. static LIST *additem (list, item)   /* Adds LIST item onto end of LIST list */
  315. register LIST   *list;
  316. LIST            *item;
  317. {
  318.     PP_DBG (("ch_bind/additem (list, item)"));
  319.     
  320.     if (list == NULL)
  321.         return (item);
  322.     list->li_next = additem (list->li_next, item);
  323.     return (list);
  324. }
  325.  
  326. static void freelist (list)
  327. register LIST   *list;
  328. {
  329.     PP_TRACE (("ch_bind/freelist (list)"));
  330.     
  331.     if (list == NULL)
  332.         return;
  333.     freelist (list->li_next);
  334.     free ((char *)list);
  335. }
  336.  
  337. static void do_calc (mat)
  338. MAT     mat [];
  339. {
  340.     register MAT    *ptr1, *ptr2, *ptr3;
  341.     register int    i, j, k;
  342.     
  343.     PP_TRACE (("ch_bind/do_calc (mat)"));
  344.     for (i = 0; i < matsize; i++)
  345.         for (j = 0; j < matsize; j++)
  346.         {
  347.             ptr3 = &mat [j * matsize + i];
  348.             if (ptr3->m_int != 0)
  349.                 for (k = 0; k < matsize; k++)
  350.                 {
  351.                     ptr2 = &mat [i * matsize + k];
  352.                     if (ptr2->m_int != 0)
  353.                     {
  354.                         ptr1 = &mat [j * matsize + k];
  355.                         if (ptr1->m_int == 0)
  356.                         {
  357.                             ptr1->m_int = ptr2->m_int + ptr3->m_int;
  358.                             ptr1->m_list = additem (ptr1->m_list, copylist (ptr3->m_list));
  359.                             ptr1->m_list = additem (ptr1->m_list, copylist (ptr2->m_list));
  360.                         }
  361.                         else
  362.                         {
  363.                             if (ptr2->m_int + ptr3->m_int < ptr1->m_int)
  364.                             {
  365.                                 freelist (ptr1->m_list);
  366.                                 ptr1->m_list = copylist (ptr3->m_list);
  367.                                 ptr1->m_list = additem (ptr1->m_list, copylist (ptr2->m_list));
  368.                                 ptr1->m_int = ptr2->m_int + ptr3->m_int;
  369.                             }
  370.                         }
  371.                     }
  372.                 }
  373.         }
  374. }
  375.  
  376. static MAT *initmat (size)
  377. int     size;
  378. {
  379.     MAT     *mat;
  380.     int     i, j;
  381.     
  382.     PP_TRACE (("ch_bind/initmat (%d)", size));
  383.     matsize = size;
  384.     mat = (MAT *) smalloc (size * size * sizeof (MAT));
  385.     
  386.     for (i = 0; i < size; i++)
  387.         for (j = 0; j < size; j++)
  388.         {
  389.             mat [i * matsize + j].m_int = (i == j) ? 1 : 0;
  390.             mat [i * matsize + j].m_list = NULL;
  391.         }
  392.     return (mat);
  393. }
  394.  
  395. static void addmat (mat, x, y, cost, name)
  396. MAT     mat [];
  397. int     x, y, cost;
  398. char    *name;                          /* Should be Pointer to CHAN struct */
  399. {
  400.     register MAT    *tmp;
  401.     register LIST   *ptr;
  402.     
  403.     PP_TRACE (("ch_bind/addmat (mat, %d, %d, %d, %s)", x, y, cost, name));
  404.     ptr = getitem ();
  405.     ptr->li_name = name;
  406.     tmp = &mat [x * matsize + y];
  407.     if (tmp -> m_list == NULL) {
  408.         tmp->m_list = ptr;
  409.         tmp->m_int = cost;
  410.     }
  411.     else {
  412.         PP_TRACE(("Duplicate reformatter %s (clashes with %s)",name,
  413.             tmp -> m_list -> li_name));
  414.         if (cost < tmp -> m_int) {
  415.             free ((char *)tmp->m_list);
  416.             tmp -> m_list = ptr;
  417.             tmp -> m_int = cost;
  418.         }
  419.         else
  420.             free ((char *)ptr);
  421.     }
  422. }
  423.  
  424. static FILTER *getfilter ()
  425. {
  426.     register FILTER *ptr;
  427.     
  428.     PP_DBG (("ch_bind/getfilter ()"));
  429.     ptr = (FILTER *) smalloc (sizeof (FILTER));
  430.     
  431.     ptr->fil_next = NULL;
  432.     return (ptr);
  433. }
  434.  
  435. static LIST *getitem ()
  436. {
  437.     register LIST   *ptr;
  438.     
  439.     PP_DBG (("ch_bind/getitem ()"));
  440.     ptr = (LIST *) smalloc (sizeof (LIST));
  441.     ptr->li_name = NULL;
  442.     ptr->li_next = NULL;
  443.     return (ptr);
  444. }
  445.  
  446. /*              initform
  447.  *      This routine goes through the body parts
  448.  */
  449.  
  450.  
  451. static void initform ()
  452. {
  453.     register LIST_BPT       *bptptr;
  454.     TYPES                   *all, *list;
  455.     int                     count;
  456.     
  457.     PP_TRACE (("ch_bind/initform ()"));
  458.     
  459.     list = NULL;
  460.     count = 0;
  461.     for (bptptr = headers_all; bptptr != NULLIST_BPT;
  462.          bptptr = bptptr -> li_next)
  463.     {
  464.         PP_TRACE (("ch_bind/doing body part %s",
  465.                bptptr -> li_name));
  466.         all = (TYPES *) smalloc (sizeof (TYPES));
  467.         all->ty_next = list;
  468.         list = all;
  469.         all->ty_name = bptptr->li_name;
  470.         all->ty_number = count++;
  471.     }
  472.     for (bptptr = bodies_all; bptptr != NULLIST_BPT;
  473.          bptptr = bptptr -> li_next)
  474.     {
  475.         PP_TRACE (("ch_bind/doing body part %s",
  476.                bptptr -> li_name));
  477.         all = (TYPES *) smalloc (sizeof (TYPES));
  478.         all->ty_next = list;
  479.         list = all;
  480.         all->ty_name = bptptr->li_name;
  481.         all->ty_number = count++;
  482.     }
  483.     mainmatrix = initmat (count);
  484.     typelist = list;
  485. }
  486.  
  487. /*              get_formatters
  488.  * This routine will go through the list of Channels and put the
  489.  * formatters, flatteners and un-flatteners into the matrix.
  490.  */
  491.  
  492. static void get_formatters ()
  493. {
  494.     register CHAN           **chanptr;
  495.     PP_TRACE (("ch_bind/get_formatters"));
  496.     for (chanptr = ch_all; (*chanptr) != NULL; chanptr++)
  497.     {
  498.         if ((*chanptr)->ch_chan_type != CH_SHAPER)
  499.             continue;
  500.         if ((*chanptr)->ch_bpt_in == NULL 
  501.             && (*chanptr)->ch_bpt_out == NULL
  502.             && (*chanptr)->ch_hdr_out == NULL
  503.             && (*chanptr)->ch_hdr_in == NULL) {
  504.             /* Flatten/Unfflatten */
  505.             if ((*chanptr)->ch_content_out == NULL
  506.                 && (*chanptr)->ch_content_in == NULL)
  507.             {
  508.                 PP_LOG (LLOG_EXCEPTIONS,
  509.                     ("ch_bind/no content definitions for %s",
  510.                      (*chanptr)-> ch_name));
  511.             }
  512.             else if ((*chanptr)->ch_content_in != NULL)
  513.             {       /* This is Unflattener */
  514.                 unflat ((*chanptr)->ch_name,
  515.                     (*chanptr)->ch_content_in);
  516.             }
  517.                 else
  518.             {       /* This is a flattener */
  519.                 flatten ((*chanptr)->ch_name,
  520.                      (*chanptr)->ch_content_out);
  521.             }
  522.         }
  523.         
  524.         else if ((*chanptr)->ch_bpt_in != NULL 
  525.              && (*chanptr)->ch_bpt_out != NULL)
  526.             
  527.         {       /* This is Formatter */
  528.             LIST_BPT           *ix = (*chanptr)->ch_bpt_in;
  529.             for (;ix != NULLIST_BPT; ix = ix -> li_next)
  530.                 format ((*chanptr)->ch_name,
  531.                     (*chanptr)->ch_cost + 2,
  532.                     ix -> li_name,
  533.                     (*chanptr)->ch_bpt_out->li_name);
  534.             if ((*chanptr)->ch_bpt_out->li_next != NULLIST_BPT) 
  535.                 PP_LOG(LLOG_EXCEPTIONS,
  536.                        ("ch_bind mulitple bptouts specified for shaper channel '%s'",
  537.                     (*chanptr)->ch_name));
  538.             
  539.         }
  540.         
  541.         else if ((*chanptr)->ch_hdr_in != NULL 
  542.              && (*chanptr)->ch_hdr_out != NULL)
  543.             
  544.         {       /* This is Formatter */
  545.             LIST_BPT           *ix = (*chanptr)->ch_hdr_in;
  546.             for (;ix != NULLIST_BPT; ix = ix -> li_next)
  547.                 format ((*chanptr)->ch_name,
  548.                     (*chanptr)->ch_cost + 2,
  549.                     ix->li_name,
  550.                     (*chanptr)->ch_hdr_out->li_name);
  551.             if ((*chanptr)->ch_hdr_out->li_next != NULLIST_BPT) 
  552.                 PP_LOG(LLOG_EXCEPTIONS,
  553.                        ("ch_bind mulitple hdrouts specified for shaper channel '%s'",
  554.                     (*chanptr)->ch_name));
  555.         }
  556.         
  557.         else
  558.         {
  559.             PP_LOG (LLOG_EXCEPTIONS,
  560.                 ("ch_bind/ erroneous definitions for %s",
  561.                  (*chanptr)-> ch_name));
  562.         }
  563.         
  564.     }
  565. }
  566.  
  567. extern int numBps, forwMsg;
  568. extern char    *cont_822;
  569.  
  570. int ch_bind (qp, ad, p, pfmts, pbpts, pcost, punknown)
  571. Q_struct *qp;
  572. ADDR        *ad;
  573. LIST_RCHAN    *p;
  574. LIST_RCHAN    **pfmts;
  575. LIST_BPT    **pbpts;
  576. int        *pcost, *punknown;
  577. {
  578.     MAT     *mat;
  579.     CHAN    *out_chan;
  580.     TYPES   *chan, *messty, *outty, *hdrty, *t2, *ty = NULL;
  581.     LIST    *list = NULL, *worklist;
  582.     LIST_BPT    *new_bpt = NULLIST_BPT;
  583.     LIST_RCHAN    *new_chan;
  584.     FILTER  *filt;
  585.     FLAT    *flat;
  586.     char    *filtername, *in_content;
  587.     int     cost, ind, unknownOutBP;
  588.     
  589.     *pfmts = NULLIST_RCHAN;
  590.     *pcost = 0;
  591.     *pbpts = NULLIST_BPT;
  592.     
  593.     PP_TRACE (("ch_bind ()"));
  594.     
  595.     
  596.     /*    in_content = ch_inbound->ch_content_in; */
  597.     in_content = qp -> cont_type;
  598.     if (p == NULLIST_RCHAN)
  599.         err_abrt (RP_MECH, "No channel in address for %s",
  600.               ad -> ad_value);
  601.     out_chan = p->li_chan;
  602.     
  603.     /* Messty - EITs within the message */
  604.     messty = addchantypes (qp -> encodedinfo.eit_types, 
  605.                    punknown);
  606.     
  607. #if PP_DEBUG > 1
  608.     if (pp_log_norm -> ll_events & LLOG_DEBUG) {
  609.         /* Testing Blurb */
  610.         if (out_chan->ch_hdr_out) {
  611.             chan = addchantypes (out_chan->ch_hdr_out,
  612.                          &unknownOutBP);
  613.             if (unknownOutBP == TRUE)
  614.                 PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound header(s)",
  615.                        out_chan->ch_name));
  616.             PP_DBG (("ch_bind/Channel %s supports headers ->", out_chan->ch_name));
  617.             for (; chan != NULL; chan = chan->ty_next)
  618.                 PP_DBG (("\t`%s'", chan->ty_name));
  619.             PP_DBG (("EOL"));
  620.         }
  621.         if (out_chan->ch_bpt_out) {
  622.             chan = addchantypes (out_chan->ch_bpt_out,
  623.                          &unknownOutBP);
  624.             if (unknownOutBP == TRUE)
  625.                 PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound bodypart(s)",
  626.                        out_chan->ch_name));
  627.             
  628.             PP_DBG (("ch_bind/Channel %s supports bodyparts ->", out_chan->ch_name));
  629.             for (; chan != NULL; chan = chan->ty_next)
  630.                 PP_DBG (("\t`%s'", chan->ty_name));
  631.             PP_DBG (("EOL"));
  632.         }
  633.         /* End of Testing Blurb */
  634.     }
  635. #endif
  636.     worklist = NULL;
  637.     if (out_chan -> ch_hdr_out != NULLIST_BPT ||
  638.         out_chan -> ch_bpt_out != NULLIST_BPT) {
  639.         if (out_chan -> ch_bpt_out != NULLIST_BPT) {
  640.             outty = addchantypes (out_chan->ch_bpt_out,
  641.                           &unknownOutBP);
  642.             if (unknownOutBP == TRUE)
  643.                 PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound bodypart(s)",
  644.                        out_chan->ch_name));
  645.         } else 
  646.             outty = NULL;
  647.         if (out_chan -> ch_hdr_out != NULLIST_BPT) {
  648.             hdrty = addchantypes (out_chan->ch_hdr_out,
  649.                           &unknownOutBP);
  650.             if (unknownOutBP == TRUE)
  651.                 PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound header(s)",
  652.                        out_chan->ch_name));
  653.  
  654.         } else
  655.             hdrty = NULL;
  656.  
  657.         for (chan = messty; chan != NULL; chan = chan->ty_next)
  658.         {
  659.             cost = 0;
  660.  
  661.             /* SEK addchantypes is called 4 times
  662.                once on each channel - this seems excessive */
  663.  
  664.             /* SEK this loop initialises for inbound  */
  665.             for (t2 = outty; t2 != NULL; t2 = t2->ty_next)
  666.             {
  667.                 ind = chan->ty_number * matsize + t2->ty_number;
  668.                 mat = &mainmatrix[ind];
  669.                 if ((cost == 0 && mat->m_int != 0) ||
  670.                     (cost != 0 && cost > mat->m_int
  671.                      && mat->m_int != 0))
  672.                 {
  673.                     list = mat->m_list;
  674.                     cost = mat->m_int;
  675.                     ty = t2;
  676.                 }
  677.             }
  678.  
  679.             if (cost == 0) {
  680.                 for (t2 = hdrty; t2 != NULL; t2 = t2->ty_next)
  681.                 {
  682.                     ind = chan->ty_number * matsize + t2->ty_number;
  683.                     mat = &mainmatrix[ind];
  684.                     if ((cost == 0 && mat->m_int != 0) ||
  685.                         (cost != 0 && cost > mat->m_int
  686.                          && mat->m_int != 0))
  687.                     {
  688.                         list = mat->m_list;
  689.                         cost = mat->m_int;
  690.                         ty = t2;
  691.                     }
  692.                 }
  693.             }
  694.  
  695.             if (cost == 0) {
  696.                 PP_LOG (LLOG_NOTICE,
  697.                     ("ch_bind/Can't convert %s", chan->ty_name));
  698.                 if (worklist) freelist(worklist);
  699.                 return NOTOK;
  700.             }
  701.             else {
  702.                 if (list_bpt_find (new_bpt, ty->ty_name) ==
  703.                     NULLIST_BPT)
  704.                     list_bpt_add (&new_bpt,
  705.                               list_bpt_new (ty->ty_name));
  706.                 if (cost == 1) {
  707.                     PP_TRACE (("Cost = 1"));
  708.                     continue;
  709.                 }
  710.                 else {
  711.                     worklist = inslist (worklist, 
  712.                                 copylist(list));
  713.                 }
  714.             }
  715.         }
  716.     }
  717.  
  718.     /* if NO EITS, NO unflatten! */
  719.     if (qp -> encodedinfo.eit_types != NULL) {
  720.         /* unflatten message if
  721.          *    submitted with a content and
  722.          *     either converting EITS or
  723.          *     there is a change in content type (or to none)
  724.          */
  725.         if (isstr(in_content) &&
  726.             (worklist != NULL ||
  727.              !isstr(out_chan->ch_content_out) ||
  728.              strcmp (out_chan->ch_content_out,
  729.                  in_content) != 0)) {
  730.             flat = flttype2ptr (unflatlist, in_content);
  731.             if (flat != NULL) {
  732.                 filtername = flat -> flt_name;
  733.                 PP_DBG (("ch_bind/UNFLATTEN with %s",
  734.                      filtername));
  735.                 new_chan = list_rchan_new (NULLCP, filtername);
  736.                 *pcost += new_chan -> li_chan -> ch_cost;
  737.                 list_rchan_add (pfmts, new_chan);
  738.             }
  739.             else
  740.                 PP_LOG (LLOG_EXCEPTIONS,
  741.                     ("Can't find exploder for %s",
  742.                      in_content));
  743.         }
  744.     }
  745.     /* SEK - calculate real work */
  746.     for (list = worklist; list != NULL; list = list->li_next)
  747.     {
  748.         filt = name2filter (list->li_name);
  749.         if (filt == NULL) {
  750.             PP_LOG (LLOG_EXCEPTIONS, ("No filter defined for %s",
  751.                           list -> li_name));
  752.             continue;
  753.         }
  754.         PP_DBG (("ch_bind/%s  [%s to %s]\n", filt->fil_name,
  755.              filt->fil_from, filt->fil_to));
  756.         new_chan = list_rchan_new (NULLCP, filt -> fil_name);
  757.         *pcost += new_chan -> li_chan -> ch_cost;
  758.         list_rchan_add (pfmts, new_chan);
  759.     }
  760.  
  761.     /* No EITS, No flatten */
  762.     if (qp -> encodedinfo.eit_types != NULL) {
  763.         /*
  764.          * flatten message if
  765.          *    outchan has a content and
  766.          *    message isn't straight 822 format and
  767.          *    either converting EITS or
  768.          *    changing content type (or from none)
  769.          */
  770.         if (isstr(out_chan -> ch_content_out) &&
  771.             (lexequ(out_chan->ch_content_out, cont_822) != 0
  772.              || isstr(in_content)
  773.              || numBps > 2 || forwMsg > 0) &&
  774.             (worklist != NULL || !isstr(in_content) ||
  775.              strcmp (in_content, out_chan->ch_content_out) != 0)) {
  776.             flat = flttype2ptr (flattenlist,
  777.                         out_chan->ch_content_out);
  778.             if (flat != NULL) {
  779.                 filtername = flat -> flt_name;
  780.                 PP_DBG (("ch_bind/FLATTEN with %s",
  781.                      filtername));
  782.                 new_chan = list_rchan_new (NULLCP, filtername);
  783.                 *pcost += new_chan -> li_chan -> ch_cost;
  784.                 list_rchan_add (pfmts, new_chan);
  785.             }
  786.             else
  787.                 PP_LOG (LLOG_EXCEPTIONS,
  788.                     ("Can't find flattener for %s",
  789.                      out_chan -> ch_content_out));
  790.         }
  791.     }
  792.     if (ad -> ad_content == NULLCP
  793.         && isstr (in_content) && isstr (out_chan -> ch_content_out) &&
  794.         strcmp (in_content, out_chan -> ch_content_out) != 0)
  795.         ad -> ad_content = strdup (out_chan -> ch_content_out);
  796.     else if (ad -> ad_content == NULLCP && 
  797.          isstr(out_chan -> ch_content_out))
  798.         ad -> ad_content = strdup (out_chan -> ch_content_out);
  799.  
  800.         *pbpts = new_bpt;
  801.     if (worklist)  freelist(worklist);
  802.     return OK;
  803. }
  804.